import 'package:fijkplayer/fijkplayer.dart';

class IPlayer {
  static IPlayer? _instance;

  static IPlayer get instance {
    return _instance ??= IPlayer._();
  }

  IPlayer._() {
    player.addListener(observer);
  }

  void dispose() {
    player.removeListener(observer);
    release();
    _instance = null;
  }

  void observer() {
    if (player.state == FijkState.error) {
      reset();
    }
  }

  ///fplayer 就只能对应这一个 C 层的 FFPlayer
  ///在使用完成之后， fplayer 必须释放其内部 FFPlayer 所占用的资源。
  final FijkPlayer player = FijkPlayer();

  /// autoPlay 为 true 时等同于连续调用 setDataSource、prepareAsync、start
  ///可选参数 showCover 设置为 true 时，播放器会在解析完成数据后渲染第一帧视频，然后暂停。 暂停之后播放器依然继续加载数据放入缓冲中
  Future<void> play(
    String path, {
    bool autoPlay = true,
    bool showCover = true,
  }) async {
    ///目标状态 initialized
    ///初始化完成状态，和 idle 状态相比，仅是多了输入媒体数据源的信息。 同样无额外线程打开。

    await player.setDataSource(path, autoPlay: autoPlay, showCover: showCover);
  }

  ///FijkPlayer 占用较多的内存或资源，在不使用时应该主动调用接口 release 进行释放。
  Future<void> release() async {
    ///目标状态 end
    ///播放器中所有需要手动释放的内存都释放完成。
    /// 处于此状态的播放器只能等待垃圾回收进行内存释放。
    player.release();
  }

  Future<void> reset() async {
    ///目标状态 idle
    ///闲置状态，刚完成构造的 FijkPlayer 处于此状态。
    /// 此状态下播放器占用少量内存，无额外线程启动。
    /// idle 状态只能通过 setDataSource 转换为 initialized 状态
    await player.reset();
  }

  Future<void> prepared() async {
    ///准备状态 asyncPreparing <非稳定状态>
    ///异步准备状态，在 initialized 状态调用 prepareAsync 到达此状态。
    /// 这不是一个稳定状态，此状态等待特定任务完成后自动转化为 prepared 状态。
    /// 这一状态的主要准备工作是 探测媒体文件类型，打开媒体文件，打开解码器以及新建解码线程，新建数据 read 线程，打开音频输出设备，新建视频输出线程等。
    ///目标状态 asyncPreparing 完成指定任务后自动转化为此状态。
    /// 此状态下已经开始缓冲解码了一部分音视频数据，可以随时进行播放。
    await player.prepareAsync();
  }

  Future<void> start() async {
    ///目标状态 started <非稳定状态>
    ///媒体（视频、音频）正在播放中。
    await player.start();
  }

  ///音量设置范围在 [0.0, 1.0]，设置超出此范围的音量只效果无法保障。
  Future<void> setVolume(double volume) async {
    await player.setVolume(volume);
  }

  ///控制播放器进行播放进度，参数以毫秒为单位。只能在可播放状态下调用此接口
  Future<void> seekTo(int msec) async {
    await player.seekTo(msec);
  }

  ///默认播放器的循环次数是1， 即不循环播放。如果设置循环次数0，表示无限循环
  Future<void> setLoop(int loopCount) async {
    await player.setLoop(loopCount);
  }

  Future<void> setSpeed(double speed) async {
    await player.setSpeed(speed);
  }

  void enterFullScreen() {
    player.enterFullScreen();
  }

  void exitFullScreen() {
    player.exitFullScreen();
  }

  Future<void> pause() async {
    ///目标状态 paused
    ///媒体（视频、音频）播放暂停。
    await player.pause();
  }

  Future<void> stop() async {
    ///目标状态 stopped
    ///播放器各种线程占用资源都已经释放。 音频设备关闭。
    await player.stop();
  }
}
